﻿using Microsoft.Graphics.Canvas;
using Microsoft.Graphics.Canvas.Brushes;
using Microsoft.Graphics.Canvas.Effects;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using 纸片人.AttributeUsageFloder;

// https://go.microsoft.com/fwlink/?LinkId=234238 上介绍了“空白页”项模板

namespace 纸片人.PageViews
{
    [PageType("cpu","颜色选择器")]
    /// <summary>
    /// 可用于自身或导航至 Frame 内部的空白页。
    /// </summary>
    public sealed partial class ColorPickerPage : Page
    {
        double H = 180;
        double S = 100;
        double V = 100;

        /// <summary>
        /// 单色系列
        /// </summary>
        ObservableCollection<ColorInfo> SingleSeries = new ObservableCollection<ColorInfo>();

        /// <summary>
        /// 临近色系列
        /// </summary>
        ObservableCollection<ObservableCollection<ColorInfo>> ApproachingSeries = new ObservableCollection<ObservableCollection<ColorInfo>>();

        ObservableCollection<ObservableCollection<ColorInfo>> SimilarSeries = new ObservableCollection<ObservableCollection<ColorInfo>>();
        ObservableCollection<ObservableCollection<ColorInfo>> MiddleDifferenceSeries = new ObservableCollection<ObservableCollection<ColorInfo>>();
        public ObservableCollection<ObservableCollection<ColorInfo>> ComparedSeries = new ObservableCollection<ObservableCollection<ColorInfo>>();
        public ObservableCollection<ObservableCollection<ColorInfo>> ComplementarySeries = new ObservableCollection<ObservableCollection<ColorInfo>>();


        CanvasBitmap cBitmap;
        /// <summary>
        /// 色环图片
        /// </summary>
        CanvasBitmap ColorRing;

        public ColorPickerPage()
        {
            this.InitializeComponent();
            this.Loaded += ColorPickerPage_Loaded;
        }

        private void ColorPickerPage_Loaded(object sender, RoutedEventArgs e)
        {

        }

        /// <summary>
        /// 创建颜色图像
        /// </summary>
        /// <returns></returns>
        private CanvasBitmap createColorBitmap()
        {
            if (!canvas.IsLoaded)
                return null;
            Color[] colors = new Color[256 * 256];
            var hsv = new Hsv();
            hsv.H = H;
            for (int x = 0; x < 256; x++)
            {
                for (int y = 0; y < 256; y++)
                {
                    hsv.S = (double)x / (255d) * 100d;
                    hsv.V = 100d - (double)y / (255d) * 100d;
                    var color = Function.HsvToRgb(hsv);
                    colors[x + y * 256] = color;
                }
            }



            CanvasBitmap cb = CanvasBitmap.CreateFromColors(canvas.Device, colors, 256, 256);

            return cb;
        }


        /// <summary>
        /// 绘制色相条
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canvas2_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
        {
            using (var ds = args.DrawingSession)
            {
                ds.Clear(Colors.Transparent);
                var w = sender.Size.Width;
                var h = sender.Size.Height;
                var bottom = h;
                var top = 0;

                var hsv = new Hsv();

                CanvasGradientStop[] canvasGradientStop = new CanvasGradientStop[7];
                var cs = new Color[7];

                for (int i = 0; i < 7; i++)
                {
                    hsv.H = i * 60;
                    hsv.S = 100;
                    hsv.V = 100;
                    var color = Function.HsvToRgb(hsv);
                    cs[i] = color;
                }

                for (int i = 0; i < cs.Length; i++)
                {
                    canvasGradientStop[i] = new CanvasGradientStop
                    {
                        Color = cs[i],
                        Position = (float)i / (float)(cs.Length - 1)
                    };
                }

                CanvasLinearGradientBrush clgb = new CanvasLinearGradientBrush(sender.Device, canvasGradientStop);
                clgb.StartPoint = new System.Numerics.Vector2(0, 0);
                clgb.EndPoint = new System.Numerics.Vector2((float)w, 0);

                ds.FillRectangle(0, 0, (float)w, (float)h, clgb);

                var x = H / 360 * w;
                ds.DrawLine((float)x, 0, (float)x, (float)bottom, Colors.Black, 5);

            }
        }

        /// <summary>
        /// 绘制选色区域
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canvas_Draw(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.Xaml.CanvasDrawEventArgs args)
        {
            using (var ds = args.DrawingSession)
            {
                ds.Clear(Colors.Transparent);

                if (cBitmap != null)
                {
                    var w = sender.ActualWidth;
                    var h = sender.ActualHeight;

                    float x = (float)(w / cBitmap.Size.Width);
                    float y = (float)(h / cBitmap.Size.Height);

                    Transform2DEffect te = new Transform2DEffect()
                    {
                        Source = cBitmap,

                        TransformMatrix = Matrix3x2.CreateScale(x, y)

                    };

                    ds.DrawImage(te);
                    var px = S / 100d * w;
                    var py = (1d - V / 100d) * h;
                    ds.DrawCircle((float)px, (float)py, 5, Colors.White, 4f);
                    ds.DrawCircle((float)px, (float)py, 5, Colors.Black, 2f);
                    ds.DrawImage(ColorRing);
                    //ds.DrawImage(cBitmap, 0, 0,new  Rect(0, 0, cBitmap.Size.Width, cBitmap.Size.Height));
                }
            }
        }

        /// <summary>
        /// 画板床架资源
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        private void canvas_CreateResources(Microsoft.Graphics.Canvas.UI.Xaml.CanvasControl sender, Microsoft.Graphics.Canvas.UI.CanvasCreateResourcesEventArgs args)
        {


            cBitmap = createColorBitmap();
            CreateColorRing();
        }

        /// <summary>
        /// 创建色环
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        private void CreateColorRing()
        {



            using (var renderTarget = new CanvasRenderTarget(canvas.Device, 500, 500, 96))
            {
                var target = new CanvasRenderTarget(canvas.Device, 500, 500, 96);
                using (var targetDs = target.CreateDrawingSession())
                {

                    var radius = 237.5f;
                    var hsv = new Hsv();
                    hsv.S = 100;
                    hsv.V = 100;
                    for (int angle = 0; angle < 360; angle++)
                    {
                        hsv.H = angle;
                        var color = hsv.HsvToRgb();

                        //将角度转换成弧度
                        var radin = Math.PI / 180 * angle - 90;

                        var cos = (float)Math.Cos(radin);
                        var sin = (float)Math.Sin(radin);
                        Vector2 pos = new Vector2(cos, sin);
                        pos = Vector2.Multiply(radius, pos);
                        pos = Vector2.Add(pos, new Vector2(250, 250));
                        targetDs.FillCircle(pos, 12.5f, color);
                    }

                    targetDs.FillRectangle(0, 0, 30, 30, Colors.Red);
                    targetDs.FillRectangle(470, 470, 30, 30, Colors.Red);
                    targetDs.FillCircle(new Vector2(12.5f, 12.5f), 12.5f, Colors.Green);

                }

                GaussianBlurEffect gb = new GaussianBlurEffect();
                gb.Source = target;
                //gb.BlurAmount = 1;

                using (var ds = renderTarget.CreateDrawingSession())
                {

                    ds.DrawImage(target, 0, 0, new Rect(0, 0, 500, 500));

                }







                var colors = renderTarget.GetPixelColors();
                ColorRing = CanvasBitmap.CreateFromColors(canvas.Device, colors, 500, 500);

            }




        }


        /// <summary>
        /// 色相条滑动更改色相值
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void canvas2_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            H = e.Position.X / ((FrameworkElement)sender).ActualWidth * 360d;
            H = Math.Max(Math.Min(360, H), 0);

            ColorChanged();
        }

        /// <summary>
        /// 饱和度更改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void colorS_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            S = e.NewValue;

            ColorChanged();
        }



        /// <summary>
        /// 更改颜色块
        /// </summary>
        private void ColorChanged()
        {
            if (!canvas.IsLoaded || !canvas2.IsLoaded)
                return;
            cBitmap = createColorBitmap();
            canvas.Invalidate();
            canvas2.Invalidate();
            currentColorRect.Fill = new SolidColorBrush(Function.HsvToRgb(new Hsv() { H = H, S = S, V = V }));
            ChangeSingle();
            ChangeTwoColorSeries();
        }

        /// <summary>
        /// 亮度更改
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void colorV_ValueChanged(object sender, RangeBaseValueChangedEventArgs e)
        {
            V = e.NewValue;
            ColorChanged();

        }

        private void canvas_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            //if (e.Position.X > canvas.ActualWidth || e.Position.X < 0 || e.Position.Y > canvas.ActualHeight || e.Position.Y < 0)
            //return;

            V = 100d - e.Position.Y / canvas.ActualHeight * 100d;
            S = e.Position.X / canvas.ActualWidth * 100d;

            colorS.Value = S;
            colorV.Value = V;

        }


        /// <summary>
        /// 创建单色系列
        /// </summary>
        private void ChangeSingle()
        {
            if (SingleSeries.Count == 0)
            {
                for (int i = 0; i < 10; i++)
                {
                    ColorInfo info = new ColorInfo();
                    SingleSeries.Add(info);
                }
            }
            for (int i = 0; i < 10; i++)
            {
                ColorInfo info = SingleSeries[i];

                info.HSV = new Hsv();
                info.HSV.H = H;
                info.HSV.S = (10d - (double)i) / 10d * 100;
                info.HSV.V = info.HSV.S;

                var color = info.HSV.HsvToRgb();
                info.ColorBrush = new SolidColorBrush(color);
                info.Color = color;
                info.ColorName = color.ToString();
            }
        }

        private void ChangeTwoColorSeries()
        {
            //更改临近色系列
            ChangeTwoColorSeries(ApproachingSeries, 30);
            //类似色
            ChangeTwoColorSeries(SimilarSeries, 60);
            //中差色
            ChangeTwoColorSeries(MiddleDifferenceSeries, 90);
            //对比色
            ChangeTwoColorSeries(ComparedSeries, 120);
            ChangeTwoColorSeries(ComplementarySeries, 180);

        }

        /// <summary>
        /// 更改双色系列
        /// </summary>
        private void ChangeTwoColorSeries(ObservableCollection<ObservableCollection<ColorInfo>> series, int difference)
        {
            if (series.Count == 0)
            {
                for (int i = 0; i < 2; i++)
                {
                    ObservableCollection<ColorInfo> colorInfos = new ObservableCollection<ColorInfo>();
                    for (int j = 0; j < 2; j++)
                    {
                        colorInfos.Add(new ColorInfo());

                    }
                    series.Add(colorInfos);
                }
            }
            var index = 0;
            foreach (var item in series)
            {
                var temp = item[0];
                temp.HSV = new Hsv() { H = H, S = S, V = V };

                temp.Color = temp.HSV.HsvToRgb();
                temp.HSV.S = ((int)temp.HSV.S);
                temp.HSV.V = ((int)temp.HSV.V);
                temp.ColorName = temp.Color.ToString();
                temp.ColorBrush = new SolidColorBrush(temp.Color);
                temp = item[1];
                var h = index == 0 ? (H + difference) % 360 : (H - difference) % 360;

                temp.HSV = new Hsv() { H = h, S = S, V = V };
                temp.Color = temp.HSV.HsvToRgb();
                temp.ColorName = temp.Color.ToString();
                temp.ColorBrush = new SolidColorBrush(temp.Color);
                temp.HSV.S = ((int)temp.HSV.S);
                temp.HSV.V = ((int)temp.HSV.V);
                index++;
            }
        }


    }

    public class ColorInfo : DependencyObject
    {


        public Color Color
        {
            get { return (Color)GetValue(ColorProperty); }
            set { SetValue(ColorProperty, value); }
        }

        // Using a DependencyProperty as the backing store for Color.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColorProperty =
            DependencyProperty.Register("Color", typeof(Color), typeof(ColorInfo), new PropertyMetadata(Colors.Transparent, ColorCallback));

        private static void ColorCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {



        }



        public SolidColorBrush ColorBrush
        {
            get { return (SolidColorBrush)GetValue(ColorBrushProperty); }
            set { SetValue(ColorBrushProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColorBrush.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColorBrushProperty =
            DependencyProperty.Register("ColorBrush", typeof(SolidColorBrush), typeof(ColorInfo), new PropertyMetadata(new SolidColorBrush()));



        public string ColorName
        {
            get { return (string)GetValue(ColorNameProperty); }
            set { SetValue(ColorNameProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ColorName.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ColorNameProperty =
            DependencyProperty.Register("ColorName", typeof(string), typeof(ColorInfo), new PropertyMetadata(""));



        public Hsv HSV
        {
            get { return (Hsv)GetValue(HSVProperty); }
            set { SetValue(HSVProperty, value); }
        }

        // Using a DependencyProperty as the backing store for HSV.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty HSVProperty =
            DependencyProperty.Register("HSV", typeof(Hsv), typeof(ColorInfo), new PropertyMetadata(null));




    }
}
